<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref } from 'vue'
import * as monaco from 'monaco-editor'

import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'

const props = defineProps({
  modelValue: String,
  readOnly: {
    type: Boolean,
    default: false,
  },
  language: {
    type: String,
    default: 'json',
  },
  parentRef: {
    type: Object,
    default: null,
  },
})

const emit = defineEmits(['update:modelValue']);

// eslint-disable-next-line no-restricted-globals
(self as any).MonacoEnvironment = {
  getWorker(workerId: any, label: any) {
    if (label === 'json') {
      return new JsonWorker()
    }
    return new EditorWorker()
  },
}

const editorRef = ref()
let editorInstance: any = null

const wheelOptions = { capture: true, passive: false }
function customWheel(event: any) {
  if (!editorInstance.getDomNode().contains(event.target))
    return

  const deltaY = event.deltaY
  const scrollTop = editorInstance.getScrollTop()
  const editorHeight = editorInstance.getLayoutInfo().height
  const scrollHeight = editorInstance.getScrollHeight()

  // 判断是否滚动到底部
  const isAtBottom = scrollTop + editorHeight >= scrollHeight

  // 判断是否滚动到顶部
  const isAtTop = scrollTop <= 0

  if ((isAtTop && deltaY < 0) || (isAtBottom && deltaY > 0)) {
    event.stopPropagation() // 允许父容器滚动
  }
}

onMounted(() => {
  editorInstance = monaco.editor.create(editorRef.value, {
    tabSize: 2,
    automaticLayout: true,
    scrollBeyondLastLine: false,
    value: props.modelValue, // 编辑器初始显示文字
    language: props.language, // 此处使用的python，其他语言支持自行查阅demo
    theme: 'vs', // 官方自带三种主题vs, hc-black, or vs-dark
    selectOnLineNumbers: true, // 显示行号
    roundedSelection: false,
    readOnly: props.readOnly, // 只读
    cursorStyle: 'line', // 光标样式
    glyphMargin: true, // 字形边缘
    useTabStops: false,
    fontSize: 14, // 字体大小
    autoIndent: 'advanced', // 自动布局
    quickSuggestionsDelay: 100, // 代码提示延时
    lineNumbersMinChars: 1,
    minimap: {
      enabled: false, // 关闭小地图,
    },
  })

  editorInstance.onDidChangeModelContent(() => {
    const value = editorInstance.getValue()
    emit('update:modelValue', value)
  })

  // 滚动事件处理
  if (props.parentRef) {
    props.parentRef.addEventListener('wheel', customWheel, wheelOptions)
  }
})

onBeforeUnmount(() => {
  if (editorInstance) {
    editorInstance.dispose() // 清理编辑器实例和监听器
    editorInstance = null
  }

  if (props.parentRef) {
    props.parentRef.removeEventListener('wheel', customWheel, wheelOptions)
  }
})
</script>

<template>
  <div ref="editorRef" class="editor" />
</template>

<style scoped>
.editor {
  height: 100%;
}

/* 去除光标所在行边框 */
.editor :deep() .view-overlays .current-line {
  border: none;
}

/* 去除光标所在行边框 */
.editor :deep() .view-overlays.focused .current-line {
  background-color: #f9f9f9;
}
</style>
